﻿// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#nullable disable

namespace StyleCop.Analyzers.Test
{
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.CodeAnalysis.Testing;
    using Xunit;
    using static StyleCop.Analyzers.Test.Verifiers.StyleCopDiagnosticVerifier<TestHelper.ExclusionTestAnalyzer>;

    /// <summary>
    /// Unit tests for testing exclusion of auto generated files.
    /// </summary>
    public class ExclusionTests
    {
        /// <summary>
        /// Gets the statements that will be used in the theory test cases.
        /// </summary>
        /// <value>
        /// The statements that will be used in the theory test cases.
        /// </value>
        public static IEnumerable<object[]> ShouldBeExcluded
        {
            get
            {
                yield return new[] { "Test.cs", string.Empty };
                yield return new[] { "Test.cs", "   " };
                yield return new[] { "Test.cs", "\r\n\r\n" };
                yield return new[] { "Test.cs", "\t" };
                yield return new[] { "Test.designer.cs", "class Foo { }" };
                yield return new[] { "Test.cs", "// <auto-generated" };
                yield return new[] { "Test.cs", "// <autogenerated" };
            }
        }

        /// <summary>
        /// Gets the statements that will be used in the theory test cases.
        /// </summary>
        /// <value>
        /// The statements that will be used in the theory test cases.
        /// </value>
        public static IEnumerable<object[]> ShouldNotBeExcluded
        {
            get
            {
                yield return new[] { "Test.designerr.cs", "class Foo { }" };
                yield return new[] { "Test.cs", "// <auto--generated" };
                yield return new[] { "Test.cs", "/// <auto-generated" };
                yield return new[] { "Test.cs", "\t\r\n class Foo { }" };
            }
        }

        /// <summary>
        /// Verifies that the source file is excluded from analysis.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="testCode">The code to test.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(ShouldBeExcluded))]
        public async Task TestIsExcludedAsync(string filename, string testCode)
        {
            await new CSharpTest
            {
                TestSources =
                {
                    (filename, testCode),
                },
            }.RunAsync(CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Verifies that the source file is not excluded from analysis.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="testCode">The code to test.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(ShouldNotBeExcluded))]
        public async Task TestIsNotExcludedAsync(string filename, string testCode)
        {
            var result = Diagnostic().WithLocation(filename, 1, 1);

            var test = new CSharpTest
            {
                TestSources =
                {
                    (filename, testCode),
                },
                ExpectedDiagnostics =
                {
                    result,
                },
            };

            test.TestBehaviors |= TestBehaviors.SkipSuppressionCheck;
            await test.RunAsync(CancellationToken.None).ConfigureAwait(false);
        }
    }
}
